/*
* MemoryAccessFilter.cpp: Impletement class MemoryAccessFilter.
* The main function of this cpp file is to record every memory access address.
* By: CrossBit Group, Zhang Yichao. 2010-3-16 .
*/

#include "crossbit/GLOBAL.h"
#include "crossbit/VFilter.h"
#include "crossbit/VInst.h"

using namespace crossbit;

#define FILTER_REG1 27
#define FILTER_REG2 28

XTMemAddr MemoryAccessFilter::cur_ld_info[128] = {0};
XTMemAddr MemoryAccessFilter::cur_st_info[128] = {0};

XTUint32 MemoryAccessFilter::run(VBlock *vb)
{
	VBlock::vb_iterator I = vb->begin();

	int pl = 0, ps = 0;		// pointer to the current slot of cur_ld and cur_st

	I = vb->begin();		// start from the beginning again

	while(I != vb->end())
	{
		VInst *inst = *I;
		Opcode op = inst->getOpcode();
		if(op == OP_LD)
		{
			I = vb->insert(I, LI(inst->getOperand(2).imm, FILTER_REG1, s32));
			I++;
			I = vb->insert(I, ADD(FILTER_REG1, inst->getOperand(1).reg, FILTER_REG2, s32));
			I++;
			I = vb->insert(I, ST(FILTER_REG2, 0, (Word)(cur_ld_info + pl), s32));
			I++;
			pl++;
		}
		if(op == OP_ST)
		{
			I = vb->insert(I, LI(inst->getOperand(3).imm, FILTER_REG1, s32));
			I++;
			I = vb->insert(I, ADD(FILTER_REG1, inst->getOperand(2).reg, FILTER_REG2, s32));
			I++;
			I = vb->insert(I, ST(FILTER_REG2, 0, (Word)(cur_st_info + ps), s32));
			I++;
			ps++;
		}
		I++;
	}

	/*
	// store the ld_num and st_num
	I--;
	I = vb->insert(I, LI(pl, FILTER_REG1, s32));
	I++;
	I = vb->insert(I, ST(FILTER_REG1, 0, (Word)(&GLOBAL::ld_num), s32));
	I++;
	I = vb->insert(I, LI(ps, FILTER_REG1, s32));
	I++;
	I = vb->insert(I, ST(FILTER_REG1, 0, (Word)(&GLOBAL::st_num), s32));
	I++;
	*/

	vb->Set_LD_count( pl );
	vb->Set_ST_count( ps );

	return 0;
}

XTUint32 MemoryAccessFilter::finalize(VBlock *vb)
{
	XTMemAddr entry = vb->enterSPC();

	for(int i = 0; i < vb->Get_LD_count(); i++)
	{
		GLOBAL::ma_ld_info[entry].push_back(cur_ld_info[i]);
	}
	for(int i = 0; i < vb->Get_ST_count(); i++)
	{
		GLOBAL::ma_st_info[entry].push_back(cur_st_info[i]);
	}
	return 0;
}
